#include "stdafx.h"
#include "XSystemServiceImpl.h"

#include <process.h>
#include <shellapi.h>

IMPLEMENT_SKIN_CLASS(CXSystemServiceImpl);


CXSystemServiceImpl::CXSystemServiceImpl()
{
    m_hThread = NULL;
    m_bStop = FALSE;
}

CXSystemServiceImpl::~CXSystemServiceImpl()
{
}

//////////////////////////////////////////////////////////////////////////
// IXSystemService
HRESULT CXSystemServiceImpl::ExecProgram(IN eSysExecType eType, IN LPCTSTR szFile, IN LPCTSTR szParams)
{
    ExeProgData data;
    data.eType = eType;
    data.strFile = (szFile == NULL) ? _T("") : szFile;
    data.strParams = (szParams == NULL) ? _T("") : szParams;

    {
        XAutoLock autolock(&m_DataLock);
        m_ExeProgDataContainter.push_back(data);
    }

    if(m_hThread == NULL)
    {
        m_hThread = (HANDLE)_beginthreadex(0, 0, &CXSystemServiceImpl::ExecProgramThread, (void*)this, 0, 0);
    }
    else
    {
        m_ThreadLock.UnLock();
    }

    return S_OK;
}

//////////////////////////////////////////////////////////////////////////
// IBaseObj
void CXSystemServiceImpl::OnFinalRelease()
{
    superclass::OnFinalRelease();

    if(m_hThread != NULL)
    {
        m_bStop = TRUE;
        m_ThreadLock.UnLock();

        if(WaitForSingleObject(m_hThread, 2000) != WAIT_OBJECT_0)
        {
            TerminateThread(m_hThread, 1);
        }
        CloseHandle(m_hThread);
        m_hThread = NULL;
    }
}

//////////////////////////////////////////////////////////////////////////
// CXSystemServiceImpl
unsigned CXSystemServiceImpl::ExecProgramThread(void* pParam)
{
    CXSystemServiceImpl* pThis = (CXSystemServiceImpl*)pParam;
    return pThis->ExecProgramProc();
}

unsigned CXSystemServiceImpl::ExecProgramProc()
{
    while(true)
    {
        m_ThreadLock.Lock();
        if(m_bStop)
            break;

        size_t nCount = 1;
        while(!m_bStop)
        {
            {
                XAutoLock autolock(&m_DataLock);
                nCount = m_ExeProgDataContainter.size();
                if(nCount <= 0)
                    break;
            }

            ExeProgData data;
            {
                XAutoLock autolock(&m_DataLock);
                data = m_ExeProgDataContainter.front();
                m_ExeProgDataContainter.pop_front();
            }

            SHELLEXECUTEINFO info = {0};
            info.cbSize = sizeof(info);
            info.fMask = SEE_MASK_DOENVSUBST | SEE_MASK_FLAG_LOG_USAGE | SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC | SEE_MASK_FLAG_DDEWAIT;
            info.hwnd = ::GetDesktopWindow();
            info.lpFile = data.strFile.GetData();
            info.lpParameters = data.strParams.GetData();
            info.nShow = SW_SHOWNORMAL;
            switch(data.eType)
            {
            case XSys_Exec_Edit:
                {
                    info.lpVerb = _T("edit");
                    break;
                }
            case XSys_Exec_Explore:
                {
                    info.lpVerb = _T("explore");
                    break;
                }
            case XSys_Exec_Find:
                {
                    info.lpVerb = _T("find");
                    break;
                }
            case XSys_Exec_Open:
                {
                    info.lpVerb = _T("open");
                    break;
                }
            case XSys_Exec_Print:
                {
                    info.lpVerb = _T("print");
                    break;
                }
            case XSys_Exec_Properties:
                {
                    info.lpVerb = _T("properties");
                    break;
                }
            }
            ::ShellExecuteEx(&info);
        }
    }
    return 0;
}
